﻿using System;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Threading;

using Microsoft.AspNetCore.Cryptography.KeyDerivation;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.DependencyInjection;

namespace DPConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            //HelloWorld();
            //HelloHash();
            ProtectInTimeSpan();

        }

        private static void HelloWorld()
        {
            Console.WriteLine("Hello World!");
            var sc = new ServiceCollection();
            sc.AddDataProtection();
            var services = sc.BuildServiceProvider();

            var dpProvider = services.GetDataProtectionProvider();

            var dp = services.GetDataProtector("Amadeus.DP.Console", "Amadeus");
            var protectData = dp.Protect("Hello world!");
            Console.WriteLine($"========{protectData}");
            var dp2 = services.GetDataProtector("Amadeus.DP.Console");
            var dp3 = dp2.CreateProtector("Amadeus");
            var text = dp3.Unprotect(protectData);
            Console.WriteLine($"=========={text}");


            //var instance = ActivatorUtilities.CreateInstance<MyClass>(services);
            //instance.RunSample();
            //instance.DecrypteTest();
        }

        private static void HelloHash()
        {
            var pwd = "1qaz2wsxE";
            byte[] salt = new byte[128 / 8];
            using (var rng = RandomNumberGenerator.Create())
            {
                rng.GetBytes(salt);
            }

            Console.WriteLine($"Salt: {Convert.ToBase64String(salt)}");

            // derive a 256-bit subkey (use HMACSHA1 with 10,000 iterations)
            string hashed = Convert.ToBase64String(KeyDerivation.Pbkdf2(
                password: pwd,
                salt: salt,
                prf: KeyDerivationPrf.HMACSHA1,
                iterationCount: 10000,
                numBytesRequested: 256 / 8));
            Console.WriteLine($"Hashed: {hashed}");
        }

        private static void ProtectInTimeSpan()
        {
            // create a protector for my application

            var provider = DataProtectionProvider.Create("Amadeus.DPConsole");
            var baseProtector = provider.CreateProtector("Contoso.TimeLimitedSample");

            // convert the normal protector into a time-limited protector
            var timeLimitedProtector = baseProtector.ToTimeLimitedDataProtector();

            // get some input and protect it for five seconds
            Console.Write("Enter input: ");
            string input = Console.ReadLine();
            string protectedData = timeLimitedProtector.Protect(input, lifetime: TimeSpan.FromSeconds(5));
            Console.WriteLine($"Protected data: {protectedData}");

            // unprotect it to demonstrate that round-tripping works properly
            string roundtripped = timeLimitedProtector.Unprotect(protectedData);
            Console.WriteLine($"Round-tripped data: {roundtripped}");

            // wait 6 seconds and perform another unprotect, demonstrating that the payload self-expires
            Console.WriteLine("Waiting 6 seconds...");
            Thread.Sleep(6000);
            timeLimitedProtector.Unprotect(protectedData);
        }
        
        private static void ConfigDataProtection()
        {
            var sc = new ServiceCollection();
            sc.AddDataProtection()
                .SetApplicationName("Amadeus.DPConsole")
                .ProtectKeysWithCertificate(new X509Certificate2(""));

        }
    
    
    }

    public class MyClass
    {
        IDataProtector _protector;

        // the 'provider' parameter is provided by DI
        public MyClass(IDataProtectionProvider provider)
        {
            _protector = provider.CreateProtector("hello.world");

            //_protector = provider.CreateProtector("Contoso.MyClass.v1");
        }

        public void RunSample()
        {
            Console.Write("Enter input: ");
            string input = Console.ReadLine();

            // protect the payload
            string protectedPayload = _protector.Protect(input);
            Console.WriteLine($"Protect returned: {protectedPayload}");

            // unprotect the payload
            string unprotectedPayload = _protector.Unprotect(protectedPayload);
            Console.WriteLine($"Unprotect returned: {unprotectedPayload}");
        }

        public void DecrypteTest()
        {
            var str = "CfDJ8Ay8nyusaspLmZDwNd_3Zj61Aa7kSznjsattF5xvfrZXZ1p-yowoNJY6NPtatXb8EeWsdtQPMP99-NRnvafuRTSgcMAXF1IXQgjJK98iUviq6krWuVUsGZ8qEVLmOoDqGidBrTVBcxBkzJJ3a5K8ZCCA0Ym2G7B-sJMa8JZvvB1F3aX-diqFCK12AU1KQToLo-HQjehTJDy3igQaXjmUtyxIjuAG3N4Zg9Gccku4nvJ_xlcsJDB0_kfGZ928GKXcxU3iNKHVBTS74U1_DWNWD-D4FxzhSFRkb7Y0obkecOVcuS0NodHqV4suEe8DY6lOdbYb4-olvPYOssljLW4p0vToJwuAqcUMfDYU5DVzwVNx";

            var unprotecdData = _protector.Unprotect(str);
            Console.WriteLine($"Unprotect returned: {unprotecdData}");



        }
    }
}
